#pragma once
#include "Socket.hpp"
#include "Log.hpp"
#include "Epoller.hpp"
#include <string>
#include <memory>
const int maxevent = 128;
class EpollServer
{
public:
    EpollServer(uint16_t port)
        : _port(port), _listensocket(new TcpSocket()), _epoller(new Epoller())
    {
    }
    void InitServer()
    {
        _listensocket->BuildListenSocket(_port, backlog);
        lg.LogMessage(Info, "create listensocket seccess, socket: %d\n", _listensocket->GetSockfd());

        _epoller->InitEpoller();

        _epoller->AddEvent(_listensocket->GetSockfd(), EPOLLIN);
    }
    bool Accept(std::string *peerip, uint16_t *peerport)
    {
        int sockfd = _listensocket->AcceptConnection(peerip, peerport);
        if (sockfd < 0)
        {
            lg.LogMessage(Warning, "accept error...\n");
            return false;
        }
        _epoller->AddEvent(sockfd, EPOLLIN);
        lg.LogMessage(Debug, "accept success...\n");
        return true;
    }
    int Recver(int sockfd, std::string *out)
    {
        char buffer[1024];
        int n = recv(sockfd, buffer, sizeof buffer - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            *out = buffer;
        }
        return n;
    }
    void HandlerEvent(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;
            if (events & EPOLLIN) // 读事件
            {
                if (sockfd == _listensocket->GetSockfd())
                {
                    std::string client_ip;
                    uint16_t client_port;
                    Accept(&client_ip, &client_port);
                }
                else
                {
                        std::cout << "LLLL" << std::endl;
                    std::string message;
                    int n = Recver(sockfd, &message);
                        std::cout << "LLLL" << std::endl;
                    if (n > 0)
                    {
                        std::cout << "client echo# " << message << std::endl;
                        std::string echo_message = "server echo# " + message;
                        send(sockfd, echo_message.c_str(), echo_message.size(), 0);
                    }
                    else if (n == 0)
                    {
                        lg.LogMessage(Info, "client sockfd: %d closed\n", sockfd);
                        _epoller->DelEvent(sockfd);
                        close(sockfd);
                    }
                    else
                    {
                        lg.LogMessage(Error, "client recv error, sockfd: %d\n", sockfd);
                        _epoller->DelEvent(sockfd);
                        close(sockfd);
                    }
                }
            }
        }
    }
    void Loop()
    {
        while (true)
        {
            int n = _epoller->Wait(_revs, maxevent, -1);
            switch (n)
            {
            case 0:
                lg.LogMessage(Info, "timeout...\n");
                break;
            case -1:
                lg.LogMessage(Error, "epoll_wait failed...\n");
                break;
            default:
                lg.LogMessage(Info, "event happend...\n");
                HandlerEvent(n);
                break;
            }
        }
    }

private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensocket;
    std::unique_ptr<Epoller> _epoller;
    struct epoll_event _revs[maxevent];
};